package com.childenglish.controller;

import com.childenglish.utils.R;
import com.childenglish.service.RedisService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.net.InetAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/cluster")
public class ClusterController {

    private final RedisTemplate<String, Object> redisTemplate;
    private final RedisService redisService;

    @Value("${spring.instance.id:unknown}")
    private String instanceId;

    @Value("${server.port:8080}")
    private String serverPort;

    public ClusterController(RedisTemplate<String, Object> redisTemplate, RedisService redisService) {
        this.redisTemplate = redisTemplate;
        this.redisService = redisService;
    }

    /**
     * 集群健康检查
     */
    @GetMapping("/health")
    public R clusterHealth() {
        try {
            Map<String, Object> healthData = new HashMap<>();

            // 基础信息
            healthData.put("instanceId", instanceId);
            healthData.put("port", serverPort);
            healthData.put("hostname", InetAddress.getLocalHost().getHostName());
            healthData.put("ip", InetAddress.getLocalHost().getHostAddress());
            healthData.put("timestamp", new Date());
            healthData.put("status", "UP");

            // Redis 连接检查
            try {
                redisTemplate.opsForValue().set("health_check", "ok", 10, TimeUnit.SECONDS);
                String redisStatus = (String) redisTemplate.opsForValue().get("health_check");
                healthData.put("redis", "CONNECTED");
                healthData.put("redisStatus", redisStatus);

                // 测试Redis服务
                redisService.set("service_test", "redis_service_ok", 30, TimeUnit.SECONDS);
                String serviceTest = (String) redisService.get("service_test");
                healthData.put("redisService", serviceTest);

            } catch (Exception e) {
                healthData.put("redis", "DISCONNECTED");
                healthData.put("redisError", e.getMessage());
            }

            // 会话统计
            healthData.put("activeSessions", getActiveSessionCount());

            return R.ok("集群健康状态正常").data(healthData);

        } catch (Exception e) {
            return R.error("集群健康检查失败: " + e.getMessage());
        }
    }

    /**
     * 会话测试接口
     */
    @GetMapping("/session/test")
    public R sessionTest(HttpServletRequest request) {
        HttpSession session = request.getSession();

        // 获取或创建会话数据
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        if (visitCount == null) {
            visitCount = 1;
        } else {
            visitCount++;
        }
        session.setAttribute("visitCount", visitCount);
        session.setAttribute("lastAccess", new Date());
        session.setAttribute("instanceId", instanceId);

        Map<String, Object> sessionData = new HashMap<>();
        sessionData.put("sessionId", session.getId());
        sessionData.put("visitCount", visitCount);
        sessionData.put("instanceId", instanceId);
        sessionData.put("createdTime", new Date(session.getCreationTime()));
        sessionData.put("lastAccess", new Date(session.getLastAccessedTime()));

        return R.ok("会话测试成功").data(sessionData);
    }

    /**
     * Redis操作测试接口
     */
    @PostMapping("/redis/test")
    public R redisTest(@RequestBody Map<String, Object> request) {
        try {
            String operation = (String) request.get("operation");
            String key = (String) request.get("key");
            Object value = request.get("value");
            Long timeout = request.get("timeout") != null ?
                    Long.valueOf(request.get("timeout").toString()) : null;

            Map<String, Object> result = new HashMap<>();
            result.put("operation", operation);
            result.put("key", key);

            switch (operation) {
                case "set":
                    if (timeout != null) {
                        redisService.set(key, value, timeout, TimeUnit.SECONDS);
                    } else {
                        redisService.set(key, value);
                    }
                    result.put("status", "success");
                    result.put("value", value);
                    break;

                case "get":
                    Object retrievedValue = redisService.get(key);
                    result.put("status", "success");
                    result.put("value", retrievedValue);
                    break;

                case "delete":
                    Boolean deleteResult = redisService.delete(key);
                    result.put("status", deleteResult ? "success" : "key_not_found");
                    break;

                case "exists":
                    Boolean exists = redisService.hasKey(key);
                    result.put("status", "success");
                    result.put("exists", exists);
                    break;

                case "increment":
                    Long incrementResult = redisService.increment(key,
                            value != null ? Long.valueOf(value.toString()) : 1);
                    result.put("status", "success");
                    result.put("newValue", incrementResult);
                    break;

                default:
                    result.put("status", "error");
                    result.put("message", "Unsupported operation");
                    break;
            }

            return R.ok("Redis操作成功").data(result);

        } catch (Exception e) {
            return R.error("Redis操作失败: " + e.getMessage());
        }
    }

    /**
     * 获取Redis信息
     */
    @GetMapping("/redis/info")
    public R getRedisInfo() {
        try {
            Map<String, Object> redisInfo = new HashMap<>();

            // 测试各种数据类型
            redisService.set("string_test", "Hello Redis", 300, TimeUnit.SECONDS);
            redisInfo.put("string_test", redisService.get("string_test"));

            redisService.hSet("hash_test", "field1", "value1");
            redisService.hSet("hash_test", "field2", "value2");
            redisInfo.put("hash_test_field1", redisService.hGet("hash_test", "field1"));
            redisInfo.put("hash_test_field2", redisService.hGet("hash_test", "field2"));

            // 存储实例信息
            Map<String, Object> instanceInfo = new HashMap<>();
            instanceInfo.put("instanceId", instanceId);
            instanceInfo.put("serverPort", serverPort);
            instanceInfo.put("startupTime", new Date());

            redisService.set("instance:" + instanceId, instanceInfo, 3600, TimeUnit.SECONDS);
            redisInfo.put("storedInstanceInfo", redisService.get("instance:" + instanceId));

            return R.ok("Redis信息获取成功").data(redisInfo);

        } catch (Exception e) {
            return R.error("获取Redis信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取集群信息
     */
    @GetMapping("/info")
    public R clusterInfo() {
        Map<String, Object> clusterInfo = new HashMap<>();
        clusterInfo.put("instanceId", instanceId);
        clusterInfo.put("serverPort", serverPort);
        clusterInfo.put("startupTime", new Date());
        clusterInfo.put("activeSessions", getActiveSessionCount());
        clusterInfo.put("redisStatus", checkRedisStatus());
        clusterInfo.put("sessionStoreType", "Redis");

        return R.ok("集群信息获取成功").data(clusterInfo);
    }

    private int getActiveSessionCount() {
        try {
            // 这里可以添加获取活跃会话数的逻辑
            // 由于使用了 Redis Session，可以通过 Redis 查询
            return 0; // 简化实现
        } catch (Exception e) {
            return -1;
        }
    }

    private String checkRedisStatus() {
        try {
            redisTemplate.opsForValue().get("test");
            return "CONNECTED";
        } catch (Exception e) {
            return "DISCONNECTED: " + e.getMessage();
        }
    }
}